/**
 * 特别重要:
 * 属性值简写
 * 简写属性名只要使用变量名（不用再写冒号）就会自动被解释为同名的属性键。如果没有找到同名变量，则会抛出 ReferenceError。
 */
let nameValue = 'Matt';
let person1 = {
  nameValue
};
console.log(person1); // { name: 'Matt' }

/**
 * 特别重要:
 * 可计算属性
 * 在引入可计算属性之前，如果想使用变量的值作为属性，那么必须先声明对象，然后使用中括号语法来添加属性。换句话说，不能在对象字面量中直接动态命名属性。
 */
const nameKey = 'name';
const ageKey = 'age';
const jobKey = 'job';
let person2 = {};
person2[nameKey] = 'Matt';
person2[ageKey] = 27;
person2[jobKey] = 'Software engineer';
console.log(person2); // { name: 'Matt', age: 27, job: 'Software engineer' }

/**
 * 特别重要:
 * 可计算属性
 * 使用可计算属性在对象字面量中完成动态属性赋值。中括号包围的对象属性键告诉运行时将其作为 JavaScript 表达式而不是字符串来求值.因为被当作 JavaScript 表达式求值，所以可计算属性本身可以是复杂的表达式，在实例化时再求值.
 */
// const nameKey = 'name';
// const ageKey = 'age';
// const jobKey = 'job';
let uniqueToken = 0;
function getUniqueKey(key) {
  return `${key}_${uniqueToken++}`;
}
let person3 = {
  [getUniqueKey(nameKey)]: 'Matt',
  [getUniqueKey(ageKey)]: 27,
  [getUniqueKey(jobKey)]: 'Software engineer'
};
console.log(person3); // { name_0: 'Matt', age_1: 27, job_2: 'Software ngineer' }

/**
 * 特别重要:
 * 简写方法名
 */
let person4 = {
  sayName(name) {
    console.log(`My name is ${name}`);
  }
};
person4.sayName('Matt'); // My name is Matt

/**
 * 特别重要:
 * 简写方法名对获取函数和设置函数也是适用的：
 */
let person5 = {
  name_: '',
  get name() {
    return this.name_;
  },
  set name(name) {
    this.name_ = name;
  },
  sayName() {
    console.log(`My name is ${this.name_}`);
  }
};
person5.name = 'Matt';
person5.sayName(); // My name is Matt
console.log(Object.getOwnPropertyDescriptors(person5))
// {
//   name_: {
//     value: 'Matt',
//         writable: true,
//         enumerable: true,
//         configurable: true
//   },
//   name: {
//     get: [Function: get name],
//     set: [Function: set name],
//     enumerable: true,
//         configurable: true
//   },
//   sayName: {
//     value: [Function: sayName],
//     writable: true,
//         enumerable: true,
//         configurable: true
//   }
// }

/**
 * 特别重要:
 * 简写方法名与可计算属性键相互兼容
 */
const methodKey = 'sayName';
let person6 = {
  [methodKey](name) {
    console.log(`My name is ${name}`);
  }
};
person6.sayName('Matt'); // My name is Matt
